package com.lxy.gateway.filter;

import cn.hutool.json.JSONObject;
import com.alibaba.nacos.client.utils.IPUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 123
 * @date 2020/6/29 23:05
 * @description
 */
@Component
@Slf4j
public class IpFilter implements GlobalFilter, Ordered {

    @Value("${ip.filter.x:10}")
    private Integer minutes;
    @Value("${ip.filter.y:5}")
    private Integer times;

    //
    Map<String, List<Long>> clientRegisterMap=new ConcurrentHashMap();



    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 从上下文中取出request和response对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String path = request.getURI().getPath();
        //请求注册接口
        if(path.contains("/user/register")){

            String hostAddress = getIP(request);
            if(clientRegisterMap.get(hostAddress)==null){
                clientRegisterMap.put(hostAddress,new ArrayList<>());
            }
            List<Long> requestRegisterApiStamptimeList = clientRegisterMap.get(hostAddress);
            // 保存本次请求时间戳
            requestRegisterApiStamptimeList.add(System.currentTimeMillis());
            long intervalMinutes = System.currentTimeMillis()-minutes*60*1000;
            // 计算单位时间内的请求次数
            long count = requestRegisterApiStamptimeList.stream().filter(time -> time > intervalMinutes).count();
            // 请求次数大于上限
            if(count>times){
                // 决绝访问，返回
                response.setStatusCode(HttpStatus.OK); // 状态码
                String message="=====>IP:" + hostAddress + " "+minutes+"minutes call register api "+count+",more than"+times;
                log.debug(message);
                JSONObject jsonObject = new JSONObject(){{
                    put("code","500");
                    put("msg",message);
                }
                };
                DataBuffer wrap = response.bufferFactory().wrap(jsonObject.toString().getBytes());
                return response.writeWith(Mono.just(wrap));
            }
        }

        // 合法请求，放行，执行后续的过滤器
        return chain.filter(exchange);

    }


    @Override
    public int getOrder() {
        return 2;
    }

    public static void main(String[] args) {
        long time = DateUtils.addMinutes(new Date(), -1).getTime();
        System.out.println(new Date(time));
    }


    private static final String IP_UNKNOWN = "unknown";
    private static final String IP_LOCAL = "127.0.0.1";
    private static final int IP_LEN = 15;

    /**
     * 获取客户端真实ip
     * @param request request
     * @return 返回ip
     */
    public static String getIP(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        String ipAddress = headers.getFirst("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = headers.getFirst("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = headers.getFirst("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = Optional.ofNullable(request.getRemoteAddress())
                    .map(address -> address.getAddress().getHostAddress())
                    .orElse("");
            if (IP_LOCAL.equals(ipAddress)) {
                // 根据网卡取本机配置的IP
                try {
                    InetAddress inet = InetAddress.getLocalHost();
                    ipAddress = inet.getHostAddress();
                } catch (UnknownHostException e) {
                    // ignore
                }
            }
        }

        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > IP_LEN) {
            int index = ipAddress.indexOf(",");
            if (index > 0) {
                ipAddress = ipAddress.substring(0, index);
            }
        }
        return ipAddress;
    }
}
